+function ($) {
    'use strict';


    var bolt = {
        is_debug: false,
        KeyPressed: { //key press state
            ctrl: false,
            shift: false
        },
        tokenName: "Authorization",
        keyCode: {
            ENTER: 13, ESC: 27, END: 35, HOME: 36,
            SHIFT: 16, CTRL: 17, TAB: 9,
            LEFT: 37, RIGHT: 39, UP: 38, DOWN: 40,
            DELETE: 46, BACKSPACE: 8
        },
        eventType: {
            initUI: 'bolt.initUI',
            beforeInitUI: 'bolt.beforeInitUI',
            afterInitUI: 'bolt.afterInitUI',
            beforeAjaxPageShow :'bolt.beforeAjaxPageShow',
            afterAjaxPageShow :'bolt.afterAjaxPageShow',
            ajaxStatus: 'bolt.ajaxStatus',
            resizeGrid: 'bolt.resizeGrid',
            beforeAjaxLoad: 'bolt.beforeAjaxLoad',

            beforeLoadNavtab: 'bolt.beforeLoadNavtab',
            beforeLoadDialog: 'bolt.beforeLoadDialog',
            afterLoadNavtab: 'bolt.afterLoadNavtab',
            afterLoadDialog: 'bolt.afterLoadDialog',
            beforeCloseNavtab: 'bolt.beforeCloseNavtab',
            beforeCloseDialog: 'bolt.beforeCloseDialog',
            afterCloseNavtab: 'bolt.afterCloseNavtab',
            afterCloseDialog: 'bolt.afterCloseDialog'
        },
        pageInfo: {
            total:'totalRow',
            pageCurrent: 'pageCurrent',
            pageSize: 'pageSize',
            orderField: 'orderField',
            orderDirection: 'orderDirection'
        },

        priceFormatConfig: {currencySign: '￥', priceScale: 2, priceRoundType: 'roundhalfup', currencyUnit: '元'},
        toastrOptions: {
            "closeButton": true,
            "debug": false,
            "newestOnTop": false,
            "progressBar": false,
            "positionClass": "toast-bottom-right",
            "preventDuplicates": false,
            "onclick": null,
            "showDuration": "300",
            "hideDuration": "1000",
            "timeOut": "5000",
            "extendedTimeOut": "1000",
            "showEasing": "swing",
            "hideEasing": "linear",
            "showMethod": "fadeIn",
            "hideMethod": "fadeOut"
        }, //alertmsg display position && close timeout
        ajaxTimeout: 30000,
        componentHandlers : [],
        keys: {statusCode: 'status', message: 'message'},
        debug: function (msg) {
            if (this.is_debug) {
                if (typeof(console) != 'undefined') console.log(msg)
                else alert(msg)
            }
        },
        init: function (options) {
            var op = $.extend({}, options)
            if( window.alertify){
                alertify.defaults.transition = "slide";
                alertify.defaults.theme.ok = "btn btn-primary";
                alertify.defaults.theme.cancel = "btn btn-danger";
                alertify.defaults.theme.input = "form-control";
            }
            if(window.toastr){
                toastr.options = bolt.toastrOptions;
            }
            $('#app').initui();
            this.initResize();

        },
        initResize: function () {
            $(window).resize(function () {
                setTimeout(function () {
                    $(this).trigger(Bolt.eventType.resizeGrid)
                }, 30)
            })
        },

        regional: {},
        setRegional: function (key, value) {
            Bolt.regional[key] = value
        },
        getRegional: function (key) {
            if (String(key).indexOf('.') >= 0) {
                var msg, arr = String(key).split('.')

                for (var i = 0; i < arr.length; i++) {
                    if (!msg) msg = Bolt.regional[arr[i]]
                    else msg = msg[arr[i]]
                }

                return msg
            } else {
                return Bolt.regional[key]
            }
        },
        doRegional: function (frag, regional) {
            $.each(regional, function (k, v) {
                frag = frag.replaceAll('#' + k + '#', v)
            })

            return frag
        },
        // is ie browser
        isIE: function (ver) {
            var b = document.createElement('b')

            b.innerHTML = '<!--[if IE ' + ver + ']><i></i><![endif]-->'

            return b.getElementsByTagName('i').length === 1
        },
        notify: function (type, message, title) {
            if (type == '' || type == null) {
                type = 'info'
            }
            toastr[type](message, title)
        },
        assert: function (b, a) {
            if (!b) {
                alert(a)
            }
        },
        confirm: function (message, funOk, funCancel) {
            alertify.confirm("提示", message, funOk, funCancel).set('labels', {ok: '确定', cancel: '取消'});
        },
        StrBuilder: function () {
            return new StrBuilder()
        },
        getUniqueID: function () {
            var S4 =function() {
                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
            }
            return "UUID-" + (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
        },
        //单位转换
        sizeToByte: function (size) {
            var value = 0;

            if (size !== 0) {
                var unit = size.slice(-1).toUpperCase(),
                    kb = 1024,
                    mb = kb * 1024,
                    gb = mb * 1024;

                if (unit === 'K') {
                    value = parseFloat(size) * kb;
                } else if (unit === 'M') {
                    value = parseFloat(size) * mb;
                } else if (unit === 'G') {
                    value = parseFloat(size) * gb;
                }
            }

            return value;
        },
        isEmpty: function (value, trim) {
            return value === undefined || value === null || value.length === 0 || (trim && $.trim(value) === '');
        },
        getFileType: function (file) {
            return file.name.split('.').pop().toLowerCase();
        },
        /**
         * base64字符串传成blob
         * @param dataurl
         */
        dataURLtoBlob: function (dataurl) {
            var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
                bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
            while (n--) {
                u8arr[n] = bstr.charCodeAt(n);
            }
            return new Blob([u8arr], {type: mime});
        },
        getRequestUrl() {
            var url = location.search;
            var theRequest = new Object();
            if (url.indexOf("?") != -1) {
                var str = url.substr(1);
                var strs = str.split("&");
                for (var i = 0; i < strs.length; i++) {
                    theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
                }
            }
            return theRequest;
        },
        getAccessor : function(obj, expr) {
            var ret,p,prm = [], i;
            if( typeof expr === 'function') { return expr(obj); }
            ret = obj[expr];
            if(ret===undefined) {
                try {
                    if ( typeof expr === 'string' ) {
                        prm = expr.split('.');
                    }
                    i = prm.length;
                    if( i ) {
                        ret = obj;
                        while (ret && i--) {
                            p = prm.shift();
                            ret = ret[p];
                        }
                    }
                } catch (e) {}
            }
            return ret;
        },
        // 设置数值精度
        setScale: function (value, scale, roundingMode) {
            if (value == undefined || $.trim(value) == "") {
                value = 0;
            }
            if (roundingMode.toLowerCase() == "roundhalfup") {//往上近似
                return (Math.round(value * Math.pow(10, scale)) / Math.pow(10, scale)).toFixed(scale);
            } else if (roundingMode.toLowerCase() == "roundup") {//往下近似
                return (Math.ceil(value * Math.pow(10, scale)) / Math.pow(10, scale)).toFixed(scale);
            } else {
                return (Math.floor(value * Math.pow(10, scale)) / Math.pow(10, scale)).toFixed(scale);
            }
        },
        // 格式化商品价格货币
        priceCurrencyFormat:function(price) {
            price = Bolt.setScale(price, Bolt.priceFormatConfig.priceScale, Bolt.priceFormatConfig.priceRoundType);
            return  Bolt.priceFormatConfig.priceScale.currencySign + price;
        },

        // 格式化商品价格货币（包含货币单位）
        priceUnitCurrencyFormat:function(price) {
            price = Bolt.setScale(price, Bolt.priceFormatConfig.priceScale,Bolt.priceFormatConfig.priceRoundType);
            return  Bolt.priceFormatConfig.currencySign + price +  Bolt.priceFormatConfig.currencyUnit;
        },
        formatNumber: function (num, cent, isThousand, defaultValue) {
            if (num == undefined || num == "") {
                return defaultValue || ""
            }
            num = num.toString().replace(/\$|\,/g, "");
            if (isNaN(num)) {
                num = "0"
            }
            var sign = (num == (num = Math.abs(num)));
            num = Math.floor(num * Math.pow(10, cent) + 0.50000000001);
            var cents = num % Math.pow(10, cent);
            num = Math.floor(num / Math.pow(10, cent)).toString();
            cents = cents.toString();
            while (cents.length < cent) {
                cents = "0" + cents
            }
            if (isThousand) {
                for (var i = 0; i < Math.floor((num.length - (1 + i)) / 3); i++) {
                    num = num.substring(0, num.length - (4 * i + 3)) + "," + num.substring(num.length - (4 * i + 3))
                }
            }
            if (cent > 0) {
                return (((sign) ? "" : "-") + num + "." + cents)
            } else {
                return (((sign) ? "" : "-") + num)
            }
        },

        smartParseURL: function (url) {
            if (url.startsWith("http:") || url.startsWith("https:") || url.startsWith("//")) {
                return url
            }
            var a ='';
            if (url.startsWith(a)) {
                return url
            }
            if (url.startsWith("/")) {
                return a + url
            } else {
                return a + "/" + url
            }
        },
        numberPad: function (num, n) {
            var len = num.toString().length;
            while (len < n) {
                num = "0" + num;
                len++
            }
            return num
        }, formatDate: function (date, f) {
            if (date == undefined) {
                return ""
            }
            if (f == undefined) {
                f = "yyyy-MM-dd HH:mm:ss"
            }
            var o = {
                "M+": date.getMonth() + 1,
                "d+": date.getDate(),
                "H+": date.getHours(),
                "m+": date.getMinutes(),
                "s+": date.getSeconds(),
                "q+": Math.floor((date.getMonth() + 3) / 3),
                S: date.getMilliseconds()
            };
            if (/(y+)/.test(f)) {
                f = f.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length))
            }
            for (var k in o) {
                if (new RegExp("(" + k + ")").test(f)) {
                    f = f.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length));
                    return f
                }
            }
        },
        parseDate: function (date) {
            if (date == undefined) {
                return null
            }
            return new Date(date.replace(/-/g, "/"))
        },


        addComponent: function (component) {
            component = $.extend({runPoint: Bolt.eventType.afterAjaxPageShow, order: 100}, component);
            var expr = component.expr;
            if (expr instanceof Array) {
                expr = expr.join(",")
            }
            if (this.is_debug) {
                console.log("Adding Plugin for expr: " + expr + " at runPoint: " + component.runPoint + ", order: " + component.order)
            }
            Bolt.componentHandlers.push(component);
            Bolt.componentHandlers.sort(function (a, b) {
                return b.order - a.order
            })
        },
        runComponents: function (runPoint, $container) {
            $container = $container || $("body");
            if (this.is_debug) {
                console.log("Running Plugins for page load: " + runPoint)
            }
            $.each(Bolt.componentHandlers, function (i, component) {
                if (runPoint == component.runPoint) {
                    if (component.expr) {
                        var exprs = [];
                        if (component.expr instanceof Array) {
                            exprs = component.expr
                        } else {
                            exprs.push(component.expr)
                        }
                        $.each(exprs, function (i, expr) {
                            if (this.is_debug) {
                                console.log(" - expr: " + expr + ", order: " + component.order)
                            }
                            $(expr, $container).each(function () {
                                var $this = $(this), options = $this.data()
                                if (!$this.length) return
                                if (options.options && typeof options.options === 'string') options.options = options.options.toObj()
                                $.extend(options, typeof options.options === 'object' && options.options)
                                component.plugin.call($this, options)
                            })
                        })
                    } else {
                        if (this.is_debug) {
                            console.log(" - expr: " + component.expr + ", order: " + component.order)
                        }
                        component.plugin.call($container)
                    }
                }
            });
            $container.find(".form-control-focus:first").focus()
        }

    };

    function StrBuilder() {
        this.datas = new Array()
    }

    StrBuilder.prototype.add = function (str) {
        if (typeof str !== 'undefined') this.datas.push(str)
        return this
    }

    StrBuilder.prototype.toString = function (str) {
        var string = this.datas.join(str || '')

        this.clear()

        return string
    }

    StrBuilder.prototype.isEmpty = function () {
        return this.datas.length == 0
    }

    StrBuilder.prototype.clear = function () {
        this.datas = []
        this.datas.length = 0
    }
    window.Bolt = bolt
}(jQuery);

/**
 * JQuey　函数扩展
 */
+function ($) {
    'use strict';
    $.fieldValue = function(el, successful) {
        var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
        if (successful === undefined) {
            successful = true;
        }
        if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
            (t == 'checkbox' || t == 'radio') && !el.checked ||
            (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
            tag == 'select' && el.selectedIndex == -1)) {
            return null;
        }
        if (tag == 'select') {
            var index = el.selectedIndex;
            if (index < 0) {
                return null;
            }
            var a = [], ops = el.options;
            var one = (t == 'select-one');
            var max = (one ? index+1 : ops.length);
            for(var i=(one ? index : 0); i < max; i++) {
                var op = ops[i];
                if (op.selected) {
                    var v = op.value;
                    if (!v) { // extra pain for IE...
                        v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
                    }
                    if (one) {
                        return v;
                    }
                    a.push(v);
                }
            }
            return a;
        }
        return $(el).val();
    };
    $.fn.extend({

        /**
         * @param {Object} op: {type:GET/POST, url:ajax请求地址, data:ajax请求参数列表, callback:回调函数 }
         */
        ajaxUrl: function (op) {
            var $this = $(this), $target = $this

            if (!$target.length)
                $target = $this

            $this.trigger(Bolt.eventType.beforeAjaxLoad)

            if (op.loadingMask) {
                $target.trigger(Bolt.eventType.ajaxStatus)
            }

            $.ajax({
                type: op.type || 'GET',
                url: op.url,
                data: op.data || {},
                cache: false,
                dataType: 'html',
                timeout: Bolt.ajaxTimeout,
                success: function (response) {
                    var json = response.toJson(),wrap = null;
                    if (!json[Bolt.keys.statusCode]) {
                        if ($this.is("tbody")) {
                            wrap = $this
                        } else {
                            wrap = $("<div class='ajax-page-inner'/>").appendTo($this)
                        }

                        wrap.hide();
                        wrap.empty().html(response);
                        Bolt.runComponents(Bolt.eventType.beforeAjaxPageShow, wrap);
                        $target.trigger(Bolt.eventType.beforeAjaxPageShow)
                        wrap.show();
                        Bolt.runComponents(Bolt.eventType.afterAjaxPageShow, wrap);
                        $target.trigger(Bolt.eventType.afterAjaxPageShow)

                    } else {
                        Bolt.notify(json[Bolt.keys.statusCode], json[Bolt.keys.message]);
                    }
                    if ($.isFunction(op.callback)) op.callback(response)
                },
                statusCode: {
                    0: function (xhr, ajaxOptions, thrownError) {
                        Bolt.notify('error', Bolt.regional.ajaxnosend);
                    },
                    401: function () {
                        Bolt.notify('error', Bolt.regional.sessiontimeout);
                        window.setTimeout(function () {
                            window.location.reload(true);
                        }, 2000);
                    },
                    503: function (xhr, ajaxOptions, thrownError) {
                        Bolt.notify('error', Bolt.regional.statusCode_503);
                    }
                }
            })
        },
        loadUrl: function (url, data, callback) {
            $(this).ajaxUrl({url: url, data: data, callback: callback})
        },

        doAjax: function (op) {

            var $this = $(this), $target, $ajaxMask

            $this.data('holdSubmit', true)

            if (!op.url) {
                Bolt.debug('The ajax url is undefined!')
                return
            }
            if (!op.callback) {
                Bolt.debug('The ajax callback is undefined!')
                return
            } else {
                op.callback = op.callback.toFunc()
            }
            if (op.loadingMask) {
                $target = $this.isTag('form') ? $this.closest('.page-container') : $this

                if (!$target.length)
                    $target = $this

                $($target).trigger(Bolt.eventType.ajaxStatus)
                $ajaxMask = $target.find('> .bjui-ajax-mask')
            }
            if (!op.type) op.type = 'POST'
            if (!op.dataType) op.dataType = 'json'
            if (!op.cache) op.cache = false
            op.timeout = op.ajaxTimeout || Bolt.ajaxTimeout
            op.success = function (response) {
                if ($ajaxMask) {
                    if (op.callback) {
                        $.when(op.callback(response)).done(function () {
                            $target.trigger('Bolt.ajaxStop')
                        })
                    } else {
                        $target.trigger('Bolt.ajaxStop')
                    }
                } else {
                    op.callback(response)
                }

                $this.data('holdSubmit', false)
            }
            op.error = function (xhr, ajaxOptions, thrownError) {
                if ($ajaxMask)
                    $target.trigger('bolt.ajaxError')
                $this.DataAjax('ajaxError', xhr, ajaxOptions, thrownError)

                $this.data('holdSubmit', false)
            }
            op.statusCode = {
                0: function (xhr, ajaxOptions, thrownError) {
                    Bolt.notify('error', Bolt.regional.ajaxnosend)
                    $this.data('holdSubmit', false)
                },
                401: function () {
                    Bolt.notify('error', Bolt.regional.sessiontimeout);
                    window.setTimeout(function () {
                        window.location.reload(true);
                    }, 2000);
                },
                503: function (xhr, ajaxOptions, thrownError) {
                    Bolt.notify('error', Bolt.regional.statusCode_503)
                    $this.data('holdSubmit', false)
                }
            }

            $.ajax(op)
        },
        getPageTarget: function () {
            var $target

            if (this.closest('.bolt-layout').length) $target = this.closest('.bolt-layout')
            else if (this.closest('.navtab-panel').length) $target = $.CurrentNavtab
            else $target = $.CurrentDialog

            return $target
        },
        getMaxIndexObj: function ($elements) {
            var zIndex = 0, index = 0

            $elements.each(function (i) {
                var newZIndex = parseInt($(this).css('zIndex')) || 1

                if (zIndex < newZIndex) {
                    zIndex = newZIndex
                    index = i
                }
            })

            return $elements.eq(index)
        },
        fieldValue : function(successful) {
            for (var val=[], i=0, max=this.length; i < max; i++) {
                var el = this[i];
                var v = $.fieldValue(el, successful);
                if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
                    continue;
                }
                if (v.constructor == Array)
                    $.merge(val, v);
                else
                    val.push(v);
            }
            return val;
        },
        formToArray : function(semantic, elements) {
            var a = [];
            if (this.length === 0) {
                return a;
            }

            var form = this[0];
            var els = semantic ? form.getElementsByTagName('*') : form.elements;
            if (!els) {
                return a;
            }

            var i,j,n,v,el,max,jmax;
            for(i=0, max=els.length; i < max; i++) {
                el = els[i];
                n = el.name;
                if (!n) {
                    continue;
                }
                v = $.fieldValue(el, true);
                if (v && v.constructor == Array) {
                    if (elements)
                        elements.push(el);
                    for(j=0, jmax=v.length; j < jmax; j++) {
                        a.push({name: n, value: v[j]});
                    }
                }
                else if (el.type == 'file' && !el.disabled) {
                    if (elements)
                        elements.push(el);
                    var files = el.files , $that = $(el);
                    if(!Bolt.isEmpty($that.attr('multiple'))) {
                        if ($that.data('bolt.multipleFileInput')) {
                            files =  $that.multipleFileInput('getSource');
                            $.each(files,function (index,value) {
                                a.push({name: n, value: Bolt.dataURLtoBlob(value['value']), type: el.type});
                            })
                        }
                    }else{
                        if (files.length) {
                            for (j=0; j < files.length; j++) {
                                a.push({name: n, value: files[j], type: el.type});
                            }
                        }else {
                            // #180
                            a.push({ name: n, value:'', type: el.type });
                        }
                    }
                }
                else if (v !== null && typeof v != 'undefined') {
                    if (elements)
                        elements.push(el);
                    a.push({name: n, value: v, type: el.type, required: el.required});
                }
            }
            return a;
        },
        /**
         * 将表单数据转成JSON对象 用法：$(form).serializeJson()
         */
        serializeJson: function () {
            var o = {}
            var a = this.serializeArray()

            $.each(a, function () {
                if (o[this.name] !== undefined) {
                    if (!o[this.name].push) {
                        o[this.name] = [o[this.name]]
                    }
                    o[this.name].push(this.value || '')
                } else {
                    o[this.name] = this.value || ''
                }
            })

            return o
        },
        setForm: function (jsonValue) {
            var obj = $(this);
            $.each(jsonValue, function (name, ival) {
                var $oinput = obj.find("input[name=" + name + "]");
                if ($oinput.attr("type") == "radio" || $oinput.attr("type") == "checkbox") {
                    $oinput.each(function () {
                        if (Object.prototype.toString.apply(ival) == '[object Array]') {//是复选框，并且是数组
                            for (var i = 0; i < ival.length; i++) {
                                if ($(this).val() == ival[i])
                                    $(this).attr("checked", "checked");
                            }
                        } else {

                            if ($(this).val() == ival) {
                                $(this).attr("checked", "checked");
                            } else if ($(this).val() == String(ival)) {
                                $(this).attr("checked", "checked");
                            }

                        }
                    });
                } else if ($oinput.attr("type") == "textarea") {//多行文本框
                    obj.find("[name=" + name + "]").html(ival);
                } else {
                    obj.find("[name=" + name + "]").val(ival);
                }
            });
        },
        clearForm: function (t) {
            return this.each(function () {
                $("input,select,textarea", this).clearFields(t)
            })
        },
        clearFields: function (t) {
            var r = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;
            return this.each(function () {
                var a = this.type, n = this.tagName.toLowerCase();
                r.test(a) || "textarea" == n ? this.value = "" : "checkbox" == a || "radio" == a ? this.checked = !1 : "select" == n ? this.selectedIndex = -1 : "file" == a ? /MSIE/.test(navigator.userAgent) ? e(this).replaceWith(e(this).clone(!0)) : e(this).val("") : t && (t === !0 && /hidden/.test(a) || "string" == typeof t && e(this).is(t)) && (this.value = "")
            })
        },

        resetForm : function () {
            return this.each(function () {
                ("function" == typeof this.reset || "object" == typeof this.reset && !this.reset.nodeType) && this.reset()
            })
        },

        selected : function (t) {
            return void 0 === t && (t = !0), this.each(function () {
                var r = this.type;
                if ("checkbox" == r || "radio" == r) {
                    this.checked = t
                } else {
                    if ("option" == this.tagName.toLowerCase()) {
                        var a = e(this).parent("select");
                        t && a[0] && "select-one" == a[0].type && a.find("option").selected(!1), this.selected = t
                    }
                }
            })
        },

        isTag: function (tn) {
            if (!tn) return false
            if (!$(this).prop('tagName')) return false
            return $(this)[0].tagName.toLowerCase() == tn ? true : false
        },
        /**
         * 判断当前元素是否已经绑定某个事件
         * @param {Object} type
         */
        isBind: function (type) {
            var _events = $(this).data('events')
            return _events && type && _events[type]
        },
        /**
         * 输出firebug日志
         * @param {Object} msg
         */
        log: function (msg) {
            return this.each(function () {
                if (console) console.log('%s: %o', msg, this)
            })
        }
    })

    /**
     * 扩展String方法
     */
    /**
     * 扩展String方法
     */
    $.extend(String.prototype, {
        isPositiveInteger: function () {
            return (new RegExp(/^[1-9]\d*$/).test(this))
        },
        isInteger: function () {
            return (new RegExp(/^\d+$/).test(this))
        },
        isNumber: function () {
            return (new RegExp(/^([-]{0,1}(\d+)[\.]+(\d+))|([-]{0,1}(\d+))$/).test(this))
        },
        includeChinese: function () {
            return (new RegExp(/[\u4E00-\u9FA5]/).test(this))
        },
        trim: function () {
            return this.replace(/(^\s*)|(\s*$)|\r|\n/g, '')
        },
        startsWith: function (pattern) {
            return this.indexOf(pattern) === 0
        },
        endsWith: function (pattern) {
            var d = this.length - pattern.length
            return d >= 0 && this.lastIndexOf(pattern) === d
        },
        replaceSuffix: function (index) {
            return this.replace(/\[[0-9]+\]/, '[' + index + ']').replace('#index#', index)
        },
        replaceSuffix2: function (index) {
            return this.replace(/\-(i)([0-9]+)$/, '-i' + index).replace('#index#', index)
        },
        trans: function () {
            return this.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"')
        },
        encodeTXT: function () {
            return (this).replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll(' ', '&nbsp;')
        },
        replaceAll: function (os, ns) {
            return this.replace(new RegExp(os, 'gm'), ns)
        },
        /*替换占位符为对应选择器的值*/ //{^(.|\#)[A-Za-z0-9_-\s]*}
        replacePlh: function ($box) {
            $box = $box || $(document)
            return this.replace(/{\/?[^}]*}/g, function ($1) {
                var $input = $box.find($1.replace(/[{}]+/g, ''))

                return $input && $input.val() ? $input.val() : $1
            })
        },
        replaceMsg: function (holder) {
            return this.replace(new RegExp('({.*})', 'g'), holder)
        },
        replaceTm: function ($data) {
            if (!$data) return this

            return this.replace(RegExp('({[A-Za-z_]+[A-Za-z0-9_-]*})', 'g'), function ($1) {
                return $data[$1.replace(/[{}]+/g, '')]
            })
        },
        replaceTmById: function (_box) {
            var $parent = _box || $(document)

            return this.replace(RegExp('({[A-Za-z_]+[A-Za-z0-9_-]*})', 'g'), function ($1) {
                var $input = $parent.find('#' + $1.replace(/[{}]+/g, ''))
                return $input.val() ? $input.val() : $1
            })
        },
        isFinishedTm: function () {
            return !(new RegExp('{\/?[^}]*}').test(this))
        },
        skipChar: function (ch) {
            if (!this || this.length === 0) return ''
            if (this.charAt(0) === ch) return this.substring(1).skipChar(ch)
            return this
        },
        isValidPwd: function () {
            return (new RegExp(/^([_]|[a-zA-Z0-9]){6,32}$/).test(this))
        },
        isValidMail: function () {
            return (new RegExp(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/).test(this.trim()))
        },
        isSpaces: function () {
            for (var i = 0; i < this.length; i += 1) {
                var ch = this.charAt(i)

                if (ch != ' ' && ch != '\n' && ch != '\t' && ch != '\r') return false
            }
            return true
        },
        isPhone: function () {
            return (new RegExp(/(^([0-9]{3,4}[-])?\d{3,8}(-\d{1,6})?$)|(^\([0-9]{3,4}\)\d{3,8}(\(\d{1,6}\))?$)|(^\d{3,8}$)/).test(this))
        },
        isUrl: function () {
            return (new RegExp(/^[a-zA-z]+:\/\/([a-zA-Z0-9\-\.]+)([-\w .\/?%&=:]*)$/).test(this))
        },
        isExternalUrl: function () {
            return this.isUrl() && this.indexOf('://' + document.domain) == -1
        },
        toBool: function () {
            return (this.toLowerCase() === 'true') ? true : false
        },
        toJson: function () {
            var json = this

            try {
                if (typeof json == 'object') json = json.toString()
                if (!json.trim().match("^\{(.+:.+,*){1,}\}$")) return this
                else return eval('(' + this + ')')//JSON.parse(this)
            } catch (e) {
                return this
            }
        },
        toObj: function () {
            var obj = null

            try {
                obj = (new Function('return ' + this))()
            } catch (e) {
                obj = this
                Bolt.debug('String toObj：Parse "String" to "Object" error! Your str is: ' + this)
            }
            return obj
        },
        /**
         * String to Function
         * 参数(方法字符串或方法名)： 'function(){...}' 或 'getName' 或 'USER.getName' 均可
         * Author: K'naan
         */
        toFunc: function () {
            if (!this || this.length == 0) return undefined
            //if ($.isFunction(this)) return this

            if (this.startsWith('function')) {
                return (new Function('return ' + this))()
            }

            var m_arr = this.split('.')
            var fn = window

            for (var i = 0; i < m_arr.length; i++) {
                fn = fn[m_arr[i]]
            }

            if (typeof fn === 'function') {
                return fn
            }

            return undefined
        },
        setUrlParam: function (key, value) {
            var str = '', url = this

            if (url.indexOf('?') != -1)
                str = url.substr(url.indexOf('?') + 1)
            else
                return url + '?' + key + '=' + value

            var returnurl = '', setparam = '', arr, modify = '0'

            if (str.indexOf('&') != -1) {
                arr = str.split('&')

                for (var i in arr) {
                    if (arr[i].split('=')[0] == key) {
                        setparam = value
                        modify = '1'
                    } else {
                        setparam = arr[i].split('=')[1]
                    }
                    returnurl = returnurl + arr[i].split('=')[0] + '=' + setparam + '&'
                }

                returnurl = returnurl.substr(0, returnurl.length - 1)
                if (modify == '0') {
                    if (returnurl == str)
                        returnurl = returnurl + '&' + key + '=' + value
                }
            } else {
                if (str.indexOf('=') != -1) {
                    arr = str.split('=')
                    if (arr[0] == key) {
                        setparam = value
                        modify = '1'
                    } else {
                        setparam = arr[1]
                    }
                    returnurl = arr[0] + '=' + setparam
                    if (modify == '0') {
                        if (returnurl == str)
                            returnurl = returnurl + '&' + key + '=' + value
                    }
                } else {
                    returnurl = key + '=' + value
                }
            }
            return url.substr(0, url.indexOf('?')) + '?' + returnurl
        }
    })
    /* Function */
    $.extend(Function.prototype, {
        //to fixed String.prototype -> toFunc
        toFunc: function () {
            return this
        }
    })

    /* Array */
    $.extend(Array.prototype, {
        remove: function (index) {
            if (index < 0) return this
            else return this.slice(0, index).concat(this.slice(index + 1, this.length))
        },
        swap: function (indexA, indexB) {
            var arr = this, temp = arr[indexA]

            arr[indexA] = arr[indexB]
            arr[indexB] = temp

            return this
        },
        move: function (old_index, new_index) {
            if (old_index < 0 || new_index < 0)
                return this

            if (new_index >= this.length) {
                var k = new_index - this.length

                while ((k--) + 1) {
                    this.push(undefined)
                }
            }

            this.splice(new_index, 0, this.splice(old_index, 1)[0])

            return this
        },
        // move continuous item
        moveItems: function (startIndex, newIndex, len) {
            if (!len || newIndex == startIndex) return this

            var moveArr = this.slice(startIndex, startIndex + len)

            if (startIndex > newIndex)
                this.splice(startIndex, len)

            this.splice.apply(this, [newIndex, 0].concat(moveArr))

            if (startIndex < newIndex)
                this.splice(startIndex, len)

            return this
        },
        unique: function () {
            var temp = new Array()

            this.sort()
            for (var i = 0; i < this.length; i++) {
                if (this[i] == this[i + 1]) continue
                temp[temp.length] = this[i]
            }

            return temp
        },
        myIndexOf: function (e) {
            if (!this || !this.length) return -1

            for (var i = 0, j; j = this[i]; i++) {
                if (j == e) return i
            }

            return -1
        },
        /* serializeArray to json */
        toJson: function () {
            var o = {}
            var a = this

            $.each(a, function () {
                if (o[this.name] !== undefined) {
                    if (!o[this.name].push) {
                        o[this.name] = [o[this.name]]
                    }
                    o[this.name].push(this.value || '')
                } else {
                    o[this.name] = this.value || ''
                }
            })

            return o
        }
    })

    /* Global */
    $.isJson = function (obj) {
        var flag = true

        try {
            flag = $.parseJSON(obj)
        } catch (e) {
            return false
        }
        return flag ? true : false
    }

}(jQuery);
/*****
 * LIST GROUP组件
 */
+function ($) {
    "use strict";
    // LISTGROUP PUBLIC CLASS DEFINITION
    // =======================
    var ListGroup = function (element, options) {
        this.$element = $(element);
        this.options = options || {};
        this.init();
    };
    ListGroup.prototype.init = function () {
        var me = this;
        var $element = this.$element;
        var options = this.options;

        if (options.toggle)
            $element.attr('data-toggle', options.toggle);

        $element.on('click', '.list-group-item', function () {
            var $item = $(this);

            if (!$item.hasClass('disabled')) {

                if ($element.data('toggle') == 'items')
                    $item.toggleClass('active');
                else
                    me.unselect('*')
                        .select($item);

                if (options.click)
                    options.click.apply(this);
            }

            $item.blur();
            event.preventDefault()
        });
    };
    ListGroup.prototype.select = function (item) {
        if (item instanceof $)
            item.addClass('active');

        if (typeof item === 'string')
            item = [item];

        if (Array.isArray(item)) {
            for (var i in item) {
                var val = item[i];
                this.$element
                    .find('.list-group-item[data-value=\'' + val + '\']')
                    .addClass('active');
            }
        }
        return this;
    };

    ListGroup.prototype.unselect = function (selector) {
        this.$element
            .find('.list-group-item')
            .filter(selector || '*')
            .removeClass('active');
        return this;
    };
    function Plugin(option) {
        return this.each(function (i, element) {
            var $element = $(element);
            var list = $element.data('listgroup');
            if (!list)
                $element.data('listgroup', (list = $element.is('select')
                    ? new SelectList(element, option)
                    : new ListGroup(element, option)));

            if (option) {

                if (option.unselect)
                    list.unselect(option.unselect);

                if (option.select)
                    list.select(option.select);
            }
        });
    };

    $.fn.listgroup = Plugin
    $.fn.listgroup.Constructor = ListGroup;
    Bolt.addComponent({
        name: "ListGroup",
        plugin: Plugin,
        runPoint: Bolt.eventType.afterAjaxPageShow,
        expr: "div[data-toggle='listGroup']",
        order: 800
    })

}(jQuery);

//nav组件
+function ($) {
    "use strict";
    // LISTGROUP PUBLIC CLASS DEFINITION
    // =======================
    var NavGroup = function (element, options) {
        this.$element = $(element);
        this.options = options || {};
        this.init();
    };
    NavGroup.prototype.init = function () {
        var me = this;
        var $element = this.$element;
        var options = this.options;

        if (options.toggle)
            $element.attr('data-toggle', options.toggle);

        $element.on('click', 'li', function () {
            var $item = $(this);

            if (!$item.hasClass('disabled')) {

                if ($element.data('toggle') == 'items')
                    $item.toggleClass('active');
                else
                    me.unselect('*').select($item);

                if (options.click)
                    options.click.apply(this);
            }

            $item.blur();
        });
    };
    NavGroup.prototype.select = function (item) {
        if (item instanceof $)
            item.addClass('active');
        return this;
    };

    NavGroup.prototype.unselect = function (selector) {
        this.$element
            .find('li')
            .filter(selector || '*')
            .removeClass('active');
        return this;
    };
    function Plugin   (option) {
        return this.each(function (i, element) {
            var $element = $(element);
            var list = $element.data('navgroup');
            if (!list)
                $element.data('navgroup', new NavGroup(element, option));

        });
    };

    $.fn.navgroup = Plugin
    $.fn.navgroup.Constructor = NavGroup;
    Bolt.addComponent({
        name: "NavGroup",
        plugin: Plugin,
        runPoint: Bolt.eventType.afterAjaxPageShow,
        expr: "div[data-toggle='navgroup']",
        order: 800
    })

}(jQuery);


//－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－初始化
+function ($) {
    'use strict';
    var InitUI = function (element, options) {
        var $this = this
        this.$element = $(element)
        this.options = options
    }

    InitUI.DEFAULTS = {}

    InitUI.prototype.init = function () {
        var that = this, $element = that.$element
        $.when(that.initUI()).done(function () {
            $element.trigger(Bolt.eventType.afterInitUI)
        })
    }

    InitUI.prototype.initUI = function () {
        var $element = this.$element
        $.when($element.trigger(Bolt.eventType.beforeInitUI)).done(function () {
            $element.trigger(Bolt.eventType.initUI)
        })
    }

    // INITUI PLUGIN DEFINITION
    // =======================

    function Plugin(option) {
        var args = arguments, property = option

        return this.each(function () {
            var $this = $(this),
                options = $.extend({}, InitUI.DEFAULTS, $this.data(), typeof option === 'object' && option),
                data = $this.data('bolt.initui')

            if (!data) $this.data('bolt.initui', (data = new InitUI(this, options)))

            if (typeof property === 'string' && $.isFunction(data[property])) {
                [].shift.apply(args)
                if (!args) data[property]()
                else data[property].apply(data, args)
            } else {
                data.init();
            }
        })
    }

    var old = $.fn.initui

    $.fn.initui = Plugin
    $.fn.initui.Constructor = InitUI;

    $.fn.initui.noConflict = function () {
        $.fn.initui = old
        return this
    }

    /* ajaxStatus */
    var _ajaxStatus = function ($target) {
        var $this = $target,
            $offset = $this,
            position = $this.css('position'),
            top = $this.scrollTop() || 0,
            height = ($this[0].clientHeight) / 2

        if (position == 'static') {
            $this.css('position', 'relative').data('bolt.ajax.static', true)
            $offset = $this.offsetParent()
        }

        var zIndex = parseInt($offset.css('zIndex')) || 0,
            $ajaxBackground = $this.find('> .bolt-maskBackground'),
            $ajaxProgress = $this.find('> .bolt-maskProgress')

        if (!$ajaxBackground.length) {
            $ajaxBackground = $(FRAG.maskBackground)
            $ajaxProgress = $(Bolt.doRegional(FRAG.maskProgress, Bolt.regional))
            $this.prepend($ajaxBackground).prepend($ajaxProgress)
        }

        var bgZindex = parseInt($ajaxBackground.css('zIndex')) || 0,
            prZindex = parseInt($ajaxProgress.css('zIndex')) || 0

        $ajaxBackground.css('zIndex', zIndex + 1).css('top', top)
        $ajaxProgress.css('zIndex', zIndex + 2)

        if (top)
            $ajaxProgress.css('top', top + height)

        if (height == 0) {
            setTimeout(function () {
                $ajaxProgress.css('top', $(this).scrollTop() + $this[0].clientHeight / 2)
            }, 50)
        }

        $this.off('scroll.ajaxmask').on('scroll.ajaxmask', function () {
            var top = $(this).scrollTop()

            $ajaxBackground.css('top', $this.scrollTop())
            $ajaxProgress.css('top', top + this.clientHeight / 2)
        })

        return {$bg: $ajaxBackground, $pr: $ajaxProgress}
    }

    $(document)
        .on('Bolt.ajaxStart', function (e, timeout, callback) {
            var ajaxMask = _ajaxStatus($(e.target))

            ajaxMask.$bg.fadeIn()
            ajaxMask.$pr.fadeIn()
            ajaxMask.$pr.find('.progress').animate({width: '80%'}, timeout || 500)

            if (callback) {
                setTimeout(function () {
                    callback.toFunc().call(this)
                }, 25)
            }
        })
        .on('Bolt.ajaxStop', function (e) {
            var $target = $(e.target), ajaxMask = _ajaxStatus($target)

            ajaxMask.$pr.find('.progress').animate({width: '100%'}, 'fast', function () {
                ajaxMask.$bg.remove()
                ajaxMask.$pr.remove()

                if ($target.data('bolt.ajax.static'))
                    $target.css('position', 'static')
            })
        })
        .on('Bolt.ajaxError', function (e) {
            var $target = $(e.target), ajaxMask = _ajaxStatus($target)

            ajaxMask.$bg.remove()
            ajaxMask.$pr.remove()

            if ($target.data('bolt.ajax.static'))
                $target.css('position', 'static')
        })

    $(document).on(Bolt.eventType.ajaxStatus, function (e) {
        var $target = $(e.target), ajaxMask = _ajaxStatus($target)

        $target
            .one('ajaxStart', function () {
                ajaxMask.$bg.fadeIn()
                ajaxMask.$pr.fadeIn()

                ajaxMask.$pr.find('.progress').animate({width: '10%'}, 'fast')
            })
            .one('ajaxStop', function () {
                //ajaxMask.$bg.fadeOut()
                //ajaxMask.$pr.fadeOut()
                //ajaxMask.$pr.find('.progress').animate({width:'80%'}, 'fast')
            })
            .one('ajaxError', function () {
                ajaxMask.$bg.remove()
                ajaxMask.$pr.remove()

                if ($target.data('bolt.ajax.static'))
                    $target.css('position', 'static')
            })
    })

}(jQuery);

/**
 * AJAX组件初始化
 */
+function ($) {
    'use strict';

    var DataAjax = function (element, options) {
        var $this = this

        this.$element = $(element)
        this.options = options

    }

    DataAjax.DEFAULTS = {
        okalert: true,
        reload: true,
        loadingmask: true,
        gridrefreshflag: true
    }

    DataAjax.prototype.ajaxError = function (xhr, ajaxOptions, thrownError) {
        var msg = xhr.responseText, that = this,
            options = that.$element.data('bolt.ajax.options') || that.options, failCallback = options.failCallback

        if (typeof msg === 'string' && msg.startsWith('{')) {
            var json = msg.toObj()
            Bolt.notify(json[Bolt.keys.statusCode], json[Bolt.keys.message]);
        } else {
            Bolt.notify('error', '<div>Http status: ' + xhr.status + ' ' + xhr.statusText + '</div>'
                + '<div>ajaxOptions: ' + ajaxOptions + ' </div>'
                + '<div>thrownError: ' + thrownError + ' </div>'
                + '<div>' + msg + '</div>')
        }

        if (failCallback) {
            if (typeof failCallback === 'string')
                failCallback = failCallback.toFunc()
            if (typeof failCallback === 'function')
                failCallback.apply(that, [msg, options])
            else
                Bolt.debug('The callback function \'failCallback\' is incorrect: ' + failCallback)
        }
    }


    DataAjax.prototype.ajaxDone = function (json) {
        if (json[Bolt.keys.statusCode] != 'success') {
            if (json[Bolt.keys.message]) Bolt.notify(json[Bolt.keys.statusCode], json[Bolt.keys.message])
        }
    }


    DataAjax.prototype.ajaxcallback = function (json) {
        var that = this, options = that.options,
            okCallback = options.okCallback, errCallback = options.errCallback, okAfterCallback = options.okAfterCallback

        var okFunc = function () {
                if (typeof okCallback === 'string')
                    okCallback = okCallback.toFunc()
                if (typeof okCallback === 'function')

                    okCallback.apply(that, [json['data']?json['data']:json, options])
                else
                    Bolt.debug('The callback function \'okCallback\' is incorrect: ' + okCallback)
            },
            okAfterFunc = function () {
                if (typeof okAfterCallback === 'string')
                    okAfterCallback = okAfterCallback.toFunc()
                if (typeof okAfterCallback === 'function')
                    okAfterCallback.apply(that, [json, options])
                else
                    Bolt.debug('The callback function \'okAfterCallback\' is incorrect: ' + okAfterCallback)
            },
            errFunc = function () {
                if (typeof errCallback === 'string')
                    errCallback = errCallback.toFunc()
                if (typeof errCallback === 'function')
                    errCallback.apply(that, [json, options])
                else
                    Bolt.debug('The callback function \'errCallback\' is incorrect: ' + errCallback)
            }

        if (typeof json === 'string')
            json = json.toObj()

        if (options.okalert)
            that.ajaxDone(json)

        if (!json[Bolt.keys.statusCode]) {
            if (okCallback) {
                okFunc()
                return
            }
        }
        if (json[Bolt.keys.statusCode] == 'success') {
            if (okCallback) {
                okFunc()
                return
            }
            Bolt.notify(json[Bolt.keys.statusCode], json[Bolt.keys.message])
            if (that.$target == $.CurrentDialog) {
                that.dialogCallBack(json)
            }
            if (okAfterCallback) {
                okAfterFunc()
            }
        } else {
            if (errCallback) {
                errFunc()
            }
        }
    }


    DataAjax.prototype.doajax = function (options) {
        var that = this, $target, $element = that.$element
        if (!options) options = {}
        if (!options.loadingMask) options.loadingMask = false

        options = $.extend({}, DataAjax.DEFAULTS, typeof options === 'object' && options)
        that.options = options

        if (options.target) {
            if (options.target instanceof jQuery)
                $target = options.target
            else
                $target = $(options.target)
        } else {
            if ($element[0] !== $('body')[0]) {
                $target = $element.find('.page-container')
            }
        }

        if (!$target || !$target.length)//tab未实现时暂用body
            $target = $.CurrentDialog || $('body').find('.page-container')

        that.$target = $target

        if (!options.url) {
            Bolt.debug('Bolt.ajax: \'doajax\' method: the url is undefined!')
            return
        } else {
            options.url = decodeURI(options.url).replacePlh($target)

            if (!options.url.isFinishedTm()) {
                Bolt.notify('error', (options.warn || Bolt.regional.plhmsg))
                Bolt.debug('Bolt.ajax: \'doajax\' method: The url is incorrect: ' + options.url)
                return
            }

            options.url = encodeURI(options.url)
        }

        var callback = options.callback && options.callback.toFunc()
        var todo = function () {
            if (!options.callback)
                options.callback = $.proxy(function (data) {
                    that.ajaxcallback(data)
                }, that)

            $target.data('bolt.ajax.options', options).doAjax(options)
        }

        if (options.confirmMsg) {
            Bolt.confirm(options.confirmMsg, todo, null)
        } else {
            todo()
        }
    }


    DataAjax.prototype.dialogCallBack = function (json) {
        Bolt.dialog('closeCurrent')
    }

    DataAjax.prototype.ajaxSearch = function ($form, options) {
        var that = this,
            $target = null,
            beforeSubmit = options.beforeSubmit,
            callback = options.callback, formData = $form.serializeJson(), postData = {},
            isSubmit = false;

        if (!options.dataGrid) options.dataGrid = $form.attr("dataGrid");
        if ($form.data('holdSubmit')) {
            return
        }
        // beforeSubmit
        if (beforeSubmit) {
            if (typeof beforeSubmit === 'string')
                beforeSubmit = beforeSubmit.toFunc()
            if (typeof beforeSubmit === 'function') {
                if (!beforeSubmit.apply(that, [$form])) {
                    return
                }
            } else {
                Bolt.debug('BJUI.ajax: \'ajaxform\' options \'beforeSubmit\': Not a function!')
                return
            }
        }

        // search for datagrid
        if (options.dataGrid) {
            var $datagrid = options.dataGrid

            if (!($datagrid instanceof jQuery)) {
                $datagrid = $($datagrid)
            }

            if (!$datagrid || !$datagrid.length || !$datagrid.data('bolt.table')) {
                Bolt.debug('BJUI.ajax: \'ajaxsearch\' method: The options \'searchDatagrid\' is not incorrect!')
                return
            }
            var toDo = function (value) {
                var filter = value.split(":");
                if (filter.length > 1) {
                    var matchValue = formData[filter[0]], matchType = filter[1];
                    postData[matchType] = matchValue
                }
            }
            if (formData['filters']) {
                var filters = formData['filters'];
                if ($.isArray(filters)) {
                    $.each(filters, function (index, value) {
                        toDo(value)
                    })
                } else {
                    toDo(filters)
                }
                delete formData['filters'];
            }
            options.url = options.url || $form.attr('action')
            if (options.url) {
                postData.dataUrl = options.url
            }
            $.extend(postData,formData);


            $datagrid.boltDataGrid('refresh', postData)

            $form.data('holdSubmit', true)

            $datagrid.on('load-success.bs.table', function () {
                $form.data('holdSubmit', false)
            })

            return
        }

    }

    /**
     * ajax表单提交
     * @param $form
     * @param options
     */
    DataAjax.prototype.ajaxForm = function ($form, options) {
        var that = this,
            $target = null,
            beforeSubmit = options.beforeSubmit,
            callback = options.callback,
            isSubmit = false, enctype;


        // beforeSubmit
        if (beforeSubmit) {
            if (typeof beforeSubmit === 'string')
                beforeSubmit = beforeSubmit.toFunc()
            if (typeof beforeSubmit === 'function') {
                if (!beforeSubmit.apply(that, [$form])) {
                    return
                }
            } else {
                Bolt.debug('Bolt.ajax: \'ajaxform\' options \'beforeSubmit\': Not a function!')
                return
            }
        }

        enctype = $form.attr('enctype')

        // target
        if (!options.target)
            options.target = $form.closest('.app-main')
        if (options.target) {
            $target = options.target

            if (!($target instanceof jQuery))
                $target = $($target)
        }
        if (!$target || !$target.length)
            $target = $.CurrentDialog

        that.$target = $target

        options.url = options.url || $form.attr('action')
        // for ie8
        if (Bolt.isIE(8) && !options.type) {
            if (!$form[0].getAttributeNode('method').specified) options.type = 'POST'
        }
        options.type = options.type || $form.attr('method') || 'POST'

        $.extend(that.options, options)

        if (callback) callback = callback.toFunc()

        var successFn = function (data, textStatus, jqXHR) {
            callback ? callback.apply(that, [data, $form]) : $.proxy(that.ajaxcallback(data), that)
        }
        var _submitFn = function () {
            var op = {
                loadingMask: true,
                type: that.options.type,
                url: that.options.url,
                callback: successFn
            }

            if (enctype && enctype == 'multipart/form-data') {
                if (window.FormData) {
                    var formData = new FormData(), a = $form.formToArray();
                    for (var i=0; i < a.length; i++) {
                        formData.append(a[i].name, a[i].value);
                    }
                    $.extend(op, {data:formData, contentType: false, processData: false})
                } else {
                    $.extend(op, {
                        data: $form.serializeArray(),
                        files: $form.find(':file'),
                        iframe: true,
                        processData: false
                    })
                }
            } else {
                $.extend(op, {data: $form.serializeArray()})
            }

            if (that.options.ajaxTimeout) op.ajaxTimeout = that.options.ajaxTimeout

            $form.doAjax(op)
        }

        if (that.options.confirmMsg) {
            Bolt.confirm(that.options.confirmMsg, _submitFn)
        } else {
            _submitFn()
        }
    }


    function Plugin(option) {
        var args = arguments,
            property = option,
            ajax = 'bolt.ajax',
            $body = $('body')
        return this.each(function () {
            var $this = $(this),
                options = $.extend({}, DataAjax.DEFAULTS, typeof option === 'object' && option),
                data = $this.data(ajax),
                func

            if (!data) {
                data = new DataAjax(this, options)
            } else {
                if (this === $body[0]) {
                    data = new DataAjax(this, options)
                } else {
                    $.extend(data.options, typeof option === 'object' && option)
                }
            }

            $this.data(ajax, data)

            if (typeof property === 'string') {
                func = data[property]
                if ($.isFunction(func)) {
                    [].shift.apply(args)
                    if (!args) func()
                    else func.apply(data, args)
                }
            }
        })
    }

    var old = $.fn.DataAjax

    $.fn.DataAjax = Plugin
    $.fn.DataAjax.Constructor = DataAjax

    Bolt.ajax = function () {
        Plugin.apply($('body'), arguments)
    }



    $(document).on(Bolt.eventType.initUI, function (e) {
        var $box = $(e.target);
        /* i-check */
        if ($.fn.iCheck) {
            $('input[data-toggle="iCheck"]',$box).extiCheck();
        }
        if ($.fn.selectpicker) {
            $('select[data-toggle="selectpicker"]', $box).extSelect();
        }
        if ($.fn.ldSelect) {
            $('[data-event="ldSelect"]', $box).ldSelect();
        }
        if ($.fn.extDateRange) {
            $('input[data-toggle="dateRange"]', $box).extDateRange();
        }
        if ($.fn.extDatePicker) {
            $('[data-toggle="date"]', $box).extDatePicker();
        }
        if ($.fn.extSelectTree) {
            $('[data-toggle="selectTree"]', $box).extSelectTree();
        }
        if ($.fn.multiSelect) {
            $('select[data-toggle="multiSelect"]', $box).extMultiSelect();
        }
        $('input[data-toggle="extBtnSearch"]', $box).extBtnSearch();

        //表单初始化
        if ($.fn.validate) {
            $('form.form-validation',$box).extValidate();
        }



        //slimscroll 初始化
        $("div[data-toggle='slimScroll']",$box).extSlimScroll();

        $("div[data-toggle='listGroup']",$box).listgroup();
    })




}(jQuery);


$(document).ready(function () {
    window.Bolt.init();
});